/**
 * @file server.cpp
 * @brief WebSocket服务器核心类的实现
 */

#include "server.hpp"
#include "../config/config.hpp"
#include "../utils/logger.hpp"
#include "../database/mysql_manager.hpp"
#include "../database/redis_manager.hpp"
#include <nlohmann/json.hpp>
#include <uuid/uuid.h>
#include <thread>
#include <chrono>

namespace {
    constexpr int BUFFER_SIZE = 4096;         ///< WebSocket消息缓冲区大小
    constexpr int SERVICE_TIMEOUT = 50;       ///< 服务循环超时时间（毫秒）
    
    /**
     * @brief 生成唯一的会话令牌
     * @return std::string UUID格式的令牌
     */
    std::string generateToken() {
        uuid_t uuid;
        uuid_generate(uuid);
        char str[37];
        uuid_unparse(uuid, str);
        return std::string(str);
    }

    /**
     * @brief 每个WebSocket连接的会话数据结构
     */
    struct PerSessionData {
        char buffer[BUFFER_SIZE];    ///< 消息缓冲区
        size_t len;                  ///< 当前缓冲区中的数据长度
    };
}

/**
 * @brief WebSocket协议定义
 */
static struct lws_protocols protocols[] = {
    {
        "game-protocol",            ///< 协议名称
        Server::wsCallback,         ///< 回调函数
        sizeof(PerSessionData),     ///< 每个会话的数据大小
        BUFFER_SIZE,                ///< 接收缓冲区大小
    },
    { nullptr, nullptr, 0, 0 }      ///< 终止项
};

Server& Server::getInstance() {
    static Server instance;
    return instance;
}

Server::~Server() {
    stop();
}

bool Server::init() {
    // 创建libwebsockets服务器配置
    struct lws_context_creation_info info;
    memset(&info, 0, sizeof(info));

    // 设置基本参数
    info.port = Config::getInstance().getPort();
    info.protocols = protocols;
    info.gid = -1;
    info.uid = -1;
    info.options = LWS_SERVER_OPTION_VALIDATE_UTF8;

    // 创建WebSocket上下文
    context_ = lws_create_context(&info);
    if (!context_) {
        Logger::getInstance().error("Failed to create LWS context");
        return false;
    }

    // 注册消息处理器
    registerMessageHandlers();

    return true;
}


// void Server::run() {
//     running_ = true;
//     Logger::getInstance().info("WebSocket server started on port {}", Config::getInstance().getPort());

//     // 主循环
//     while (running_) {
//         runOnce();
//         std::this_thread::sleep_for(std::chrono::milliseconds(10));
//     }
// }

void Server::run() {
        running_ = true;
        while (running_) {
            int num_events = epoll_wait(epoll_fd_, ...);
            for (int i = 0; i < num_events; ++i) {
                if (events[i].data.fd == signal_pipe_[0]) {
                    handleShutdownSignal();  // 处理退出事件
                }
                // 处理其他事件...
            }
        }
    }

bool Server::runOnce() {
    if (!context_ || !running_) {
        return false;
    }

    // 执行一次服务循环，处理待处理的事件
    return lws_service(context_, SERVICE_TIMEOUT) >= 0;
}

void Server::stop() {
    running_ = false;
    Logger::getInstance().info("Stopping WebSocket server...");
    
    if (context_) {
        // 给清理操作留出时间
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        lws_context_destroy(context_);
        context_ = nullptr;
    }
    
    Logger::getInstance().info("WebSocket server stopped");

    if (shutdown_callbacks_) {
        shutdown_callbacks_();
    }
}

int Server::wsCallback(struct lws *wsi, enum lws_callback_reasons reason,
                      void *user, void *in, size_t len) {
    PerSessionData *psd = static_cast<PerSessionData*>(user);

    switch (reason) {
        case LWS_CALLBACK_ESTABLISHED: {
            // 新的WebSocket连接建立
            Logger::getInstance().info("Client connected");
            break;
        }
        case LWS_CALLBACK_RECEIVE: {
            // 收到消息数据
            if (len > 0) {
                // 将数据追加到缓冲区
                memcpy(psd->buffer + psd->len, in, len);
                psd->len += len;

                // 如果是消息的最后一个片段，处理完整消息
                if (lws_is_final_fragment(wsi)) {
                    std::string message(psd->buffer, psd->len);
                    Server::getInstance().handleMessage(wsi, message);
                    psd->len = 0;
                }
            }
            break;
        }
        case LWS_CALLBACK_CLOSED: {
            // WebSocket连接关闭
            Logger::getInstance().info("Client disconnected");
            Server::getInstance().removeSession(wsi);
            break;
        }
        default:
            break;
    }

    return 0;
}

void Server::handleMessage(struct lws *wsi, const std::string& message) {
    MessageRouter::getInstance().route(wsi, message);
}

void Server::handleRegister(struct lws *wsi, const nlohmann::json& data) {
    std::string username = data["username"];
    std::string password = data["password"];
    std::string email = data["email"];

    // 创建新用户
    if (MySQLManager::getInstance().createUser(username, password, email)) {
        nlohmann::json response = {
            {"type", "register_response"},
            {"data", {
                {"success", true},
                {"message", "Registration successful"}
            }}
        };
        sendMessage(wsi, response.dump());
    } else {
        nlohmann::json response = {
            {"type", "register_response"},
            {"data", {
                {"success", false},
                {"message", "Registration failed"}
            }}
        };
        sendMessage(wsi, response.dump());
    }
}

void Server::handleLogin(struct lws *wsi, const nlohmann::json& data) {
    std::string username = data["username"];
    std::string password = data["password"];

    // 验证用户凭证
    if (MySQLManager::getInstance().validateUserCredentials(username, password)) {
        auto user = MySQLManager::getInstance().getUserByUsername(username);
        if (user) {
            // 生成会话令牌
            std::string token = generateToken();
            RedisManager::getInstance().setUserSession(token, user->id);
            RedisManager::getInstance().cacheUserData(*user);
            MySQLManager::getInstance().updateUserLastLogin(user->id);

            // 保存会话信息
            addSession(wsi, user);

            // 返回成功响应
            nlohmann::json response = {
                {"type", "login_response"},
                {"data", {
                    {"success", true},
                    {"token", token},
                    {"user", user->toJson()}
                }}
            };
            sendMessage(wsi, response.dump());
        }
    } else {
        // 返回失败响应
        nlohmann::json response = {
            {"type", "login_response"},
            {"data", {
                {"success", false},
                {"message", "Invalid credentials"}
            }}
        };
        sendMessage(wsi, response.dump());
    }
}

void Server::handleLogout(struct lws *wsi, const nlohmann::json& data) {
    std::string token = data["token"];
    // 清理会话数据
    RedisManager::getInstance().removeUserSession(token);
    removeSession(wsi);

    // 返回成功响应
    nlohmann::json response = {
        {"type", "logout_response"},
        {"data", {
            {"success", true},
            {"message", "Logout successful"}
        }}
    };
    sendMessage(wsi, response.dump());
}

void Server::sendMessage(struct lws *wsi, const std::string& message) {
    // 为LWS_PRE预留空间
    unsigned char *buf = (unsigned char*)malloc(LWS_PRE + message.length());
    memcpy(buf + LWS_PRE, message.c_str(), message.length());
    
    // 发送消息
    lws_write(wsi, buf + LWS_PRE, message.length(), LWS_WRITE_TEXT);
    free(buf);
}

// 设置shutdown callback
void Server::setShutdownCallback(std::function<void()> callback) {
    shutdown_callbacks_ = callback;
}

void Server::addSession(struct lws* wsi, std::shared_ptr<User> user) {
    sessions_[wsi] = user;
}

void Server::removeSession(struct lws* wsi) {
    sessions_.erase(wsi);
}

std::shared_ptr<User> Server::getSession(struct lws* wsi) {
    auto it = sessions_.find(wsi);
    return it != sessions_.end() ? it->second : nullptr;
} 

void Server::registerMessageHandlers() {
    MessageRouter::getInstance().registerHandler(std::make_shared<AuthHandler>());
    MessageRouter::getInstance().registerHandler(std::make_shared<RegisterHandler>());
    MessageRouter::getInstance().registerHandler(std::make_shared<LogoutHandler>());
}

